/**
 * Author Lucson
 * Desc: 由于 Vuex 在 Vue3 中的 mapState 不能愉快的使用 所以简单实现了一个具备响应式能力的 mapState
 * Use: ...toRefs(useMapState("propertyName"))
 * Use: ...toRefs(useMapSatte(["propertyName1","propertyName2"]))
 * Use: ...toRefs(useMapState("moduleName",["propertyName1","propertyName2"]))
 * Use: ...toRefs(useMapState("moduleName",{ customPropertyName1:"propertyName1", customPropertyName2:"propertyName2" }))
 */

import { useStore } from "vuex";
import { reactive, watch } from "vue";

/**
 * 注意这里的 state 只能放在 全局作用域下 否则每一次调用 返回的 state 都是一个全新的引用 则不会造成全局共享的效果
 */

// 改进思路  无需自己返回新对象  应直接返回 store 中对应的对象
let state = reactive({});
export const useMapState = (moduleName, mapper) => {
  const store = useStore();
  if (moduleName !== undefined || moduleName || moduleName !== "") {
    const module = store["state"];
    if (moduleName && !mapper) {
      if (!(moduleName instanceof Array)) {
        watch(state, (n) => (module[moduleName] = n[moduleName]));
        return (
          (state[moduleName] = module[moduleName]) === Boolean("") && state
        );
      }
      if (moduleName instanceof Array) {
        state = reactive(
          moduleName.reduce(
            (prev, stateKey) =>
              ((prev[stateKey] = module[stateKey]) === Boolean("") ||
                new TypeError("不存在此状态")) &&
              prev,
            {}
          )
        );
        watch(state, (n) => Object.assign(module, n));
        return state;
      }
    }
    if (mapper && (typeof mapper === "array" || mapper instanceof Array)) {
      if (!module[moduleName]) return new TypeError("模块不存在");
      state = reactive(
        mapper.reduce(
          (prev, stateKey) =>
            ((prev[stateKey] = module[moduleName][stateKey]) === Boolean("") ||
              new TypeError("不存在此状态")) &&
            prev,
          {}
        )
      );
      watch(state, (n) => Object.assign(module[moduleName], n));
      return state;
    }
    if (
      typeof mapper === "object" &&
      Object.prototype.toString.call(mapper) === "[object Object]"
    ) {
      state = reactive(
        Object.keys(mapper).reduce(
          (prev, stateKey) =>
            ((prev[stateKey] = module[moduleName][mapper[stateKey]]) === "" ||
              new TypeError("不存在此状态")) &&
            prev,
          {}
        )
      );
      watch(state, (n) => {
        Object.assign(
          module[moduleName],
          Object.keys(mapper).reduce((prev, stateKey) => {
            return (prev[mapper[stateKey]] = n[stateKey]) && prev;
          }, {})
        );
      });
      return state;
    }
    return new TypeError("映射参数只能是数组或对象");
  }
  return new TypeError("必须需要一个映射属性");
};
